#ifndef __BSP_ADC_H
#define __BSP_ADC_H

#include "./SYSTEM/SYS/sys.h"

/* ------------------------------------------------ ADC引脚配置参数 ------------------------------------------------ */

#define ADC_ADCX_CHY_GPIO_PORT              GPIOC
#define ADC_ADCX_CHY_GPIO_PIN               GPIO_PIN_4
#define ADC_ADCX_CHY_GPIO_CLK_ENABLE()      do{ __HAL_RCC_GPIOC_CLK_ENABLE(); }while(0)  /* PC口时钟使能 */

#define ADC_ADCX                            ADC1 
#define ADC_ADCX_CHY                        ADC_CHANNEL_14                               /* 通道Y,  0 <= Y <= 17 */ 
#define ADC_ADCX_CHY_CLK_ENABLE()           do{ __HAL_RCC_ADC1_CLK_ENABLE(); }while(0)   /* ADC1 时钟使能 */

/* ------------------------------------------------ DMA配置参数 ---------------------------------------------------- */
/* ADC单通道/多通道 DMA采集 DMA及通道 定义
 * 注意: ADC1的DMA通道只能是: DMA1_Channel1, 因此只要是ADC1, 这里是不能改动的
 *       ADC2不支持DMA采集
 *       ADC3的DMA通道只能是: DMA2_Channel5, 因此如果使用 ADC3 则需要修改
 */
#define ADC_ADCX_DMACx                      DMA1_Channel1
#define ADC_ADCX_DMACx_IRQn                 DMA1_Channel1_IRQn
#define ADC_ADCX_DMACx_IRQHandler           DMA1_Channel1_IRQHandler

#define ADC_ADCX_DMACx_IS_TC()              ( DMA1->ISR & (1 << 1) )    /* 判断 DMA1_Channel1 传输完成标志, 这是一个假函数形式,
                                                                         * 不能当函数使用, 只能用在if等语句里面 
                                                                         */
#define ADC_ADCX_DMACx_CLR_TC()             do{ DMA1->IFCR |= 1 << 1; }while(0) /* 清除 DMA1_Channel1 传输完成标志 */

/* ------------------------------------------------ 特殊通道定义 ----------------------------------------------------- */
/* ADC温度传感器通道定义 */ 
#define ADC_TEMPSENSOR_CHX                  ADC_CHANNEL_16

/* ADC内部参考电压通道定义 */ 
#define ADC_VREFINT_CHX                     ADC_CHANNEL_17

/* ------------------------------------------------- ADC通道参数 ----------------------------------------------------- */

#define ADC_CH_NUM                          3                                               /* 需要转换的通道数目 */

/* 定义通道索引 
 * - 通道14(PC4): 模拟信号采集
 * - 通道16: 内部温度传感器
 * - 通道VREFINT: 用于测量内部参考电压，校准VDDA
 */
#define ADC_CHANNEL_14_INDEX                0   /* PC4 */
#define ADC_CHANNEL_TEMPSENSOR_INDEX        1   /* 内部温度传感器 */
#define ADC_CHANNEL_VREFINT_INDEX           2   /* 内部参考电压 */

/* ------------------------------------------------ 全局变量声明 ----------------------------------------------------- */

extern ADC_HandleTypeDef g_adc_handle;                              /* ADC句柄 */
extern DMA_HandleTypeDef g_dma_adc_handle;                          /* 与ADC关联的DMA句柄(单通道) */
extern uint8_t g_adc_dma_sta;                                       /* DMA传输状态标志, 0,未完成; 1, 已完成 */
extern ADC_HandleTypeDef g_adc_nch_dma_handle;                      /* 与DMA关联的ADC句柄(多通道) */
extern DMA_HandleTypeDef g_dma_nch_adc_handle;                      /* 与ADC关联的DMA句柄(多通道) */

/* ADC采集相关全局变量 */
extern uint16_t g_adc_values[ADC_CH_NUM];                           /* 存储各通道ADC原始值 */
extern float g_adc_voltages[ADC_CH_NUM];                            /* 存储各通道电压值 */
extern float g_vdda_voltage;                                        /* 存储VDDA电压值 */

/* ADC DMA缓冲区 */
#define ADC_DMA_BUF_SIZE        50 * ADC_CH_NUM                     /* ADC DMA采集 BUF大小，应等于ADC通道数的整数倍 */
extern uint16_t g_adc_dma_buf[ADC_DMA_BUF_SIZE];                    /* ADC DMA BUF */

/* ------------------------------------------------ 函数声明 --------------------------------------------------------- */

/* 基本ADC操作函数 */
void adc_init(void);                                                /* ADC初始化 */
void adc_channel_set(ADC_HandleTypeDef *adc_handle, uint32_t ch, uint32_t rank, uint32_t stime); /* ADC通道设置 */
uint32_t adc_get_result(uint32_t ch);                               /* 获得某个通道值  */
uint32_t adc_get_result_average(uint32_t ch, uint8_t times);        /* 得到某个通道给定次数采样的平均值 */

/* DMA采集相关函数 */
void adc_dma_init(uint32_t mar);                                    /* ADC DMA采集初始化 */
void adc_dma_enable(uint16_t cndtr);                                /* 使能一次ADC DMA采集传输 */
void adc_nch_dma_init(uint32_t mar);                                /* ADC多通道 DMA采集初始化 */

/* 内部温度传感器相关函数 */
void adc_temperature_init(void);                                    /* ADC温度采集初始化函数 */
short adc_get_temperature(void);                                    /* 获取内部温度传感器温度值 */
short adc_get_temperature_from_dma(void);                           /* 从DMA缓冲区获取温度传感器温度值 */

/* ADC任务相关函数 */
void adc_task_init(void);                                           /* ADC任务初始化 */
uint8_t adc_process_data(void);                                     /* 处理ADC数据，计算电压值 */
void adc_scan_task(void);                                           /* ADC扫描任务 */

#endif
